package com.joysuch.wwyt.workflow.service.impl;

import cn.hutool.core.date.DateTime;
import cn.zlg.common.util.CollectionUtils;
import com.alibaba.fastjson.JSONObject;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.workflow.bean.WorkFlowSubmitTimeBean;
import com.joysuch.wwyt.workflow.bean.WorkFlowTaskHistoryBean;
import com.joysuch.wwyt.workflow.bean.WorkFlowTaskHistoryQueryBean;
import com.joysuch.wwyt.workflow.bean.WorkFlowTimeSliceBean;
import com.joysuch.wwyt.workflow.entity.WorkFlowTask;
import com.joysuch.wwyt.workflow.entity.WorkFlowTaskAssignHistory;
import com.joysuch.wwyt.workflow.entity.WorkFlowTaskHistory;
import com.joysuch.wwyt.workflow.enums. MonitoringPointTypes;
import com.joysuch.wwyt.workflow.enums.WorkFlowOperationEnum;
import com.joysuch.wwyt.workflow.repository.WorkFlowTaskAssignHistoryDao;
import com.joysuch.wwyt.workflow.repository.WorkFlowTaskDao;
import com.joysuch.wwyt.workflow.repository.WorkFlowTaskHistoryDao;
import com.joysuch.wwyt.workflow.service.WorkFlowTaskHistoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class WorkFlowTaskHistoryServiceImpl implements WorkFlowTaskHistoryService {

    @Autowired
    private WorkFlowTaskHistoryDao workFlowTaskHistoryDao;

    @Autowired
    private WorkFlowTaskAssignHistoryDao workFlowTaskAssignHistoryDao;

    @Autowired
    private WorkFlowTaskDao workFlowTaskDao;


    @Autowired
    private BaseUserDao baseUserDao;

    @Override
    public Page<WorkFlowTaskHistoryBean> pageList(WorkFlowTaskHistoryQueryBean bean, Pageable pageable) {

        Specification<WorkFlowTaskHistory> spec = new Specification<WorkFlowTaskHistory>() {
            @Override
            public Predicate toPredicate(Root<WorkFlowTaskHistory> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                if (bean.getParentId() != null && bean.getParentId() != 0) {
                    predicates.add(cb.equal(root.get("parentId"), bean.getParentId()));
                }
                return cb.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };

        Page<WorkFlowTaskHistory> page = workFlowTaskHistoryDao.findAll(spec, pageable);
        return PageDataUtils.convertPageData(page,
                new PageDataUtils.PageDataConvert<WorkFlowTaskHistoryBean, WorkFlowTaskHistory>() {
                    @Override
                    public WorkFlowTaskHistoryBean convert(WorkFlowTaskHistory f) {
                        WorkFlowTaskHistoryBean bean = new WorkFlowTaskHistoryBean();
                        BeanUtils.copyProperties(f, bean);
                        bean.setCreateByUserName(baseUserDao.getRealNameById(bean.getCreateBy()));
                        return bean;
                    }
                });
    }


    @Override
    public WorkFlowTaskHistory findById(Long id) {
        return workFlowTaskHistoryDao.findById(id).orElse(null);
    }

    @Override
    public ResultBean workFlowTaskHis(Long taskId) {
        List<WorkFlowTaskHistory> list = workFlowTaskHistoryDao.findByParentId(taskId);
        if (CollectionUtils.isEmpty(list)) {
            return ResultBean.defaultSuccessResult();
        }
        List<Long> userIdList = list.stream().map(r -> r.getCreateBy()).distinct().collect(Collectors.toList());
        Map<Long, String> userMap = baseUserDao.findAllById(userIdList).stream().collect(Collectors.toMap(BaseUser::getId, BaseUser::getRealName));
        for (WorkFlowTaskHistory history : list) {
            history.setUserName(userMap.getOrDefault(history.getCreateBy(), ""));
            String formData = history.getFormData();
            if (StringUtils.isNotEmpty(formData)) {
                JSONObject jsonObject = JSONObject.parseObject(formData);
                String action = jsonObject.getString("action");
                history.setAction(action == null ? "" : action);
            }

        }
        return ResultBean.success(list);
    }

    @Override
    public ResultBean workFlowTaskAssignHis(String taskCode) {
        List<WorkFlowTaskAssignHistory> assignHistories = workFlowTaskAssignHistoryDao.findByTaskCodeOrderById(taskCode);
        if (CollectionUtils.isEmpty(assignHistories)) {
            return ResultBean.defaultSuccessResult();
        } else {
            List<Long> userIdList = assignHistories.stream().map(WorkFlowTaskAssignHistory::getOperator).distinct().collect(Collectors.toList());
            Map<Long, String> userMap = baseUserDao.findAllById(userIdList).stream().collect(Collectors.toMap(BaseUser::getId, BaseUser::getRealName));
            assignHistories.forEach(each -> {
                each.setOperatorName(userMap.getOrDefault(each.getOperator(), ""));
                WorkFlowOperationEnum workFlowOperationEnum = WorkFlowOperationEnum.find(each.getOperation());
                each.setOperation(workFlowOperationEnum != null ? workFlowOperationEnum.getDesc() : "");
            });
            return ResultBean.success(assignHistories);
        }
    }

    @Override
    public WorkFlowTimeSliceBean getProcessTimePeriod(WorkFlowSubmitTimeBean bean) {
        WorkFlowTimeSliceBean workFlowTimeSliceBean = new WorkFlowTimeSliceBean();
        //查看任务是否存在,不存在直接报错
        List<WorkFlowTask> workFlowTaskList = workFlowTaskDao.findAllByCode(bean.getTaskCode());
        if (CollectionUtils.isEmpty(workFlowTaskList)){
            throw new IllegalArgumentException("当前任务不存在,请检查");
        }
        WorkFlowTaskAssignHistory first = workFlowTaskAssignHistoryDao.findFirstByTaskCodeOrderById(bean.getTaskCode());
        if (first == null){
            return workFlowTimeSliceBean;
        }
        WorkFlowTaskAssignHistory last = workFlowTaskAssignHistoryDao.findLastByTaskCodeOrderById(bean.getTaskCode());
        if (last == null){
            workFlowTimeSliceBean.setProcessEnd(false);
        }
        //范围开始节点的执行信息
        WorkFlowTaskAssignHistory start = workFlowTaskAssignHistoryDao.findOneByTaskCodeAndNextTaskNameOrderByIdAsc(bean.getTaskCode(), bean.getProcessStartName());
        //范围结束节点的执行信息
        WorkFlowTaskAssignHistory end = workFlowTaskAssignHistoryDao.findOneByTaskCodeAndTaskNameOrderByIdDesc(bean.getTaskCode(), bean.getProcessEndName());
        //范围开始节点是第一个节点,则取第一个节点的结束时间为返回的开始时间
        if (bean.getProcessStartName().equals(first.getTaskName())){
            workFlowTimeSliceBean.setStartTime(first.getCreateTime());
            if (end == null){
                workFlowTimeSliceBean.setSelectEnd(false);
                if (last == null){
                    //取当前时间为返回的结束时间
                    workFlowTimeSliceBean.setEndTime(DateTime.now());
                    if (MonitoringPointTypes.VIDEO.getCode().equals(bean.getType())){
                        workFlowTimeSliceBean.setTipMessage("无法获取“"+bean.getProcessEndName()+"”节点时间,视频播放至当前时间");
                    }else if (MonitoringPointTypes.TREND.getCode().equals(bean.getType())){
                        workFlowTimeSliceBean.setTipMessage("无法获取“"+bean.getProcessEndName()+"”节点时间,监测值显示到当前时间");
                    }
                }else {
                    //流程结束,选择的结束节点未执行
                    workFlowTimeSliceBean.setEndTime(last.getCreateTime());
                    if (MonitoringPointTypes.VIDEO.getCode().equals(bean.getType())){
                        workFlowTimeSliceBean.setTipMessage("无法获取“"+bean.getProcessEndName()+"”节点时间并且业务已结束,视频播放至业务结束时间");
                    }else if (MonitoringPointTypes.TREND.getCode().equals(bean.getType())){
                        workFlowTimeSliceBean.setTipMessage("无法获取“"+bean.getProcessEndName()+"”节点时间并且业务已结束,趋势图截至业务结束时间");
                    }
                }
                return compareStartAndEnd(workFlowTimeSliceBean,bean);
            }else {
                //到了选择的结束节点
                workFlowTimeSliceBean.setEndTime(end.getCreateTime());
                return compareStartAndEnd(workFlowTimeSliceBean,bean);
            }
        //范围开始节点不是第一个节点    
        }else {
            if (start == null){
                if (end != null) {
                    workFlowTimeSliceBean.setStartTime(first.getCreateTime());
                    if (MonitoringPointTypes.VIDEO.getCode().equals(bean.getType())){
                        workFlowTimeSliceBean.setTipMessage("无法获取“"+bean.getProcessStartName()+"”节点时间,视频从业务创建时间开始播放");
                    }else if (MonitoringPointTypes.TREND.getCode().equals(bean.getType())){
                        workFlowTimeSliceBean.setTipMessage("无法获取“"+bean.getProcessStartName()+"”节点时间,监测值从业务创建时间开始显示");
                    }
                    workFlowTimeSliceBean.setEndTime(end.getCreateTime());
                    return compareStartAndEnd(workFlowTimeSliceBean,bean);
                    //流程开始和结束节点都未获取到,则返回null
                }else {
                    return workFlowTimeSliceBean;
                }
                
            }else {
                //选择的开始节点执行到了
                workFlowTimeSliceBean.setStartTime(start.getCreateTime());
                if (end == null){
                    if (last == null){
                        //流程未结束,取当前时间为返回的结束时间
                        workFlowTimeSliceBean.setEndTime(DateTime.now());
                        if (MonitoringPointTypes.VIDEO.getCode().equals(bean.getType())){
                            workFlowTimeSliceBean.setTipMessage("无法获取“"+bean.getProcessEndName()+"”节点时间,视频播放至当前时间");
                        }else if (MonitoringPointTypes.TREND.getCode().equals(bean.getType())){
                            workFlowTimeSliceBean.setTipMessage("无法获取“"+bean.getProcessEndName()+"”节点时间,监测值显示到当前时间为止");
                        }
                        workFlowTimeSliceBean.setSelectEnd(false);
                    }else {
                        //流程结束,选择的结束节点未执行
                        workFlowTimeSliceBean.setEndTime(last.getCreateTime());
                        workFlowTimeSliceBean.setSelectEnd(false);
                        if (MonitoringPointTypes.VIDEO.getCode().equals(bean.getType())){
                            workFlowTimeSliceBean.setTipMessage("无法获取“"+bean.getProcessEndName()+"”节点时间,视频播放至业务结束时间");
                        }else if (MonitoringPointTypes.TREND.getCode().equals(bean.getType())){
                            workFlowTimeSliceBean.setTipMessage("无法获取“"+bean.getProcessStartName()+"”节点时间,监测值显示至业务结束时间");
                        }
                    }
                }else {
                    //到了选择的结束节点
                    workFlowTimeSliceBean.setEndTime(end.getCreateTime());
                }
                return compareStartAndEnd(workFlowTimeSliceBean,bean);
            }
        }
    }
    
    private WorkFlowTimeSliceBean compareStartAndEnd(WorkFlowTimeSliceBean bean ,WorkFlowSubmitTimeBean timeBean){
        //两个时间都存在了,判断前后,是否需要交换位置
        //开始时间在结束时间之后,交换位置
        if (bean.getStartTime() != null && bean.getEndTime() != null){
            if (bean.getStartTime().after(bean.getEndTime())){
                Date temp = bean.getStartTime();
                bean.setStartTime(bean.getEndTime());
                bean.setEndTime(temp);
            }
            bean.setTaskCode(timeBean.getTaskCode());
        }
        return bean;
    }
}
